//	*** TODO ***
//	Implement row styles, global styles
//	======================================================================
//	File:    Flv_List.h - Flv_List implementation
//	Program: Flv_List - FLTK Widget
//	Version: 0.1.0
//	Started: 11/21/99
//
//	Copyright (C) 1999 Laurence Charlton
//
//	Description:
//	Flv_List implements a scrollable list.  No data is stored
//	in the widget.  Supports headers/footers, natively supports a single
//	row height per list.	Row grids can be turned on and off.  Supports
//	no scroll bars as well as horizontal/vertical automatic or always
//	on scroll bars.
//	Uses absolute row references.
//
//	row -1 is defined as the row header
//	row -2 is defined as the row footer
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//	======================================================================

#ifndef Flv_List_H
#define Flv_List_H

#include <FL/Fl.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Scrollbar.H>
#include <FL/Enumerations.H>
#include <FL/Flv_Style.H>

#ifndef FLTK_2
#define text_color() FL_BLACK
#define text_font() FL_HELVETICA
#define text_size() 12

//#define fl_inactive inactive
//#define fl_contrast(x,y) FL_BLACK
#define selection_text_color() FL_WHITE
#define FL_DAMAGE_HIGHLIGHT FL_DAMAGE_CHILD
#define label_font labelfont
#define label_size labelsize
#define label_color labelcolor
#define label_type labeltype
#endif

#define FLV_ROW_HEADER -1
#define FLV_ROW_FOOTER -2
#define FLV_TITLE -3

#define SLIDER_WIDTH 17

typedef unsigned char Flv_ShowScrollbar;
typedef unsigned short Flv_Feature;

//	Call back events
#define FLVE_ROW_CHANGED        1
#define FLVE_ROWS_CHANGED       2
#define FLVE_SELECTION_CHANGED  3
#define FLVE_COL_CHANGED        4
#define FLVE_COLS_CHANGED       5
#define FLVE_FEATURE_CHANGED    6
#define FLVE_CLICKED						7
#define FLVE_ENTER_PRESSED      8
#define FLVE_ROW_HEADER_CLICKED 9
#define FLVE_ROW_FOOTER_CLICKED 10
#define FLVE_COL_HEADER_CLICKED 11
#define FLVE_COL_FOOTER_CLICKED 12
#define FLVE_LABEL_CLICKED			13
#define FLVE_TITLE_CLICKED			14
#define FLVE_ALL_CLICKED				15

//	Call back when flags
#define FLVEcb_ROW_CHANGED        0x0001
#define FLVEcb_ROWS_CHANGED       0x0002
#define FLVEcb_SELECTION_CHANGED  0x0004
#define FLVEcb_COL_CHANGED        0x0008
#define FLVEcb_COLS_CHANGED       0x0010
#define FLVEcb_FEATURE_CHANGED    0x0020
#define FLVEcb_CLICKED						0x0040
#define FLVEcb_ENTER_PRESSED      0x0080
#define FLVEcb_ROW_HEADER_CLICKED 0x0100
#define FLVEcb_ROW_FOOTER_CLICKED 0x0200
#define FLVEcb_COL_HEADER_CLICKED 0x0400
#define FLVEcb_COL_FOOTER_CLICKED 0x0800
#define FLVEcb_LABEL_CLICKED			0x1000
#define FLVEcb_TITLE_CLICKED			0x2000
#define FLVEcb_ALL_CLICKED				0x4000

//	Feature list
#define FLVF_NONE							0
#define FLVF_ROW_HEADER				1
#define FLVF_ROW_FOOTER				2
#define FLVF_ROW_DIVIDER			4
#define FLVF_COL_HEADER				8
#define FLVF_COL_FOOTER			 16
#define FLVF_COL_DIVIDER		 32
#define FLVF_MULTI_SELECT		 64
#define FLVF_ROW_SELECT			128
#define FLVF_PERSIST_SELECT	256
#define FLVF_FULL_RESIZE    512
#define FLVF_DIVIDERS			(FLVF_COL_DIVIDER|FLVF_ROW_DIVIDER)
#define FLVF_HEADERS			(FLVF_ROW_HEADER|FLVF_COL_HEADER)
#define FLVF_FOOTERS			(FLVF_ROW_FOOTER|FLVF_COL_FOOTER)
#define FLVF_ROW_ENDS			(FLVF_ROW_HEADER|FLVF_ROW_FOOTER)
#define FLVF_COL_ENDS			(FLVF_COL_HEADER|FLVF_COL_FOOTER)
#define FLVF_ALL_ROW			(FLVF_ROW_HEADER|FLVF_ROW_FOOTER|FLVF_ROW_DIVIDER)
#define FLVF_ALL_COL			(FLVF_COL_HEADER|FLVF_COL_FOOTER|FLVF_COL_DIVIDER)

//	Scroll bar visibility
#define FLVS_NONE	0
#define FLVS_HORIZONTAL	1
#define FLVS_VERTICAL		2
#define FLVS_BOTH				(FLVS_HORIZONTAL|FLVS_VERTICAL)

#define FLVS_AUTOMATIC	0
#define FLVS_ALWAYS			4

#define FLVS_HORIZONTAL_ALWAYS	(FLVS_HORIZONTAL|FLVS_ALWAYS)
#define FLVS_VERTICAL_ALWAYS		(FLVS_VERTICAL|FLVS_ALWAYS)
//#define FLVS_BOTH_ALWAYS				(FLVS_BOTH|FLVS|FLVS_ALWAYS)
#define FLVS_BOTH_ALWAYS				(FLVS_BOTH|FLVS_ALWAYS)

//	Edit when constants
#define FLV_EDIT_ALWAYS				1
#define FLV_EDIT_AUTOMATIC    2
#define FLV_EDIT_MANUAL		    3

class FL_EXPORT Flv_List : public Fl_Group
{
public:
    Fl_Scrollbar scrollbar;	// Vertical scrollbar
    Fl_Scrollbar hscrollbar;	// Horizontal scrollbar

    Fl_Scrollbar *get_scrollbar()
    {
        return &scrollbar;
    };
    Fl_Scrollbar *get_hscrollbar()
    {
        return &hscrollbar;
    };

    Flv_List( int X, int Y, int W, int H, const char *l=0 );
    ~Flv_List();

    virtual int row_height( int n );
    virtual int row_height( int n, int R );

    virtual void get_style(Flv_Style &s, int R, int C=0);	//	get trickle down style

    void add_selection_style( Flv_Style &s, int R, int C=0 );	//	Add selection style

    virtual void save_editor( Fl_Widget *e, int R, int C=0 );	//	Save editor contents
    virtual void load_editor( Fl_Widget *e, int R, int C=0 );	//	Load editor contents
    virtual void position_editor( Fl_Widget *e, int x, int y, int w, int h, Flv_Style &s );

    int callback_when(void)	//	Get callback when
    {
        return vcallback_when;
    }
    int callback_when(int v)	//	Set callback when
    {
        return vcallback_when = v;
    }
    int add_callback_when(int v)	//	Add callback conditions
    {
        return vcallback_when |= v;
    }
    int clear_callback_when(int v)	//	Clear callback conditions
    {
        return vcallback_when &= ~v;
    }
    bool callback_on(int v)	//	See if callback should be done
    {
        return (vcallback_when & v)==v;
    }
    int edit_when(void)	//	Get when to edit
    {
        return vedit_when;
    }
    int edit_when( int v );	//	Set when to edit

    void start_edit(void);	//	Start editing
    void end_edit(void);	//	End editing (w/save)
    void cancel_edit(void);	//	Cancel editing (wo/save)
    Fl_Widget *editor(void)	//	Return current editor
    {
        return veditor;
    }
    int bottom_row(void);	//	Return last partially visible row

    unsigned char clicks()	//	# of clicks 1, 2, 3...
    {
        return vclicks;
    }
    void clear_clicks(void)	//	Reset # of clicks
    {
        vclicks = 0;
    }
    unsigned char max_clicks(void)	//	Get Max # of clicks
    {
        return vmax_clicks;
    }
    unsigned char max_clicks(unsigned char n)	//	Return max # of clicks
    {
        return vmax_clicks=n;
    }

    Fl_Color dead_space_color(void) const	//	Get dead space color
    {
        return vdead_space_color;
    }
    Fl_Color dead_space_color(Fl_Color n)	//	Set dead space color
    {
        return (vdead_space_color = n);
    }

    Flv_Feature feature(void)	//	Get features
    {
        return vfeature;
    }
    Flv_Feature feature(Flv_Feature v);	//	Set features
    Flv_Feature feature_add(Flv_Feature v);	//	Add (set of) feature(s)
    Flv_Feature feature_remove(Flv_Feature v);	//	Remove (set of) feature(s)
    bool feature_test(Flv_Feature v)	//	Test if (set of) feature(s) on
    {
        return ((vfeature&v)==v);
    }

    //	Convenience funtions to test if a feature is ON.
    bool row_footer(void)	//	Row footer convenience function
    {
        return feature_test(FLVF_ROW_FOOTER);
    }
    bool row_header(void)	//	Row header convenience function
    {
        return feature_test(FLVF_ROW_HEADER);
    }
    bool row_divider(void)	//	Row divider convenience function
    {
        return feature_test(FLVF_ROW_DIVIDER);
    }
    bool multi_select(void)	//	Multi-select convenience function
    {
        return feature_test(FLVF_MULTI_SELECT);
    }
    bool persist_select(void)	//	Persistant selection test
    {
        return feature_test(FLVF_PERSIST_SELECT);
    }
    bool full_resize(void)	//	Full widget resize test
    {
        return feature_test(FLVF_FULL_RESIZE);
    }

    void get_default_style( Flv_Style &s );	//	Fill in s with default style
    int get_row( int x, int y );	//	Get row from X value

    virtual bool get_cell_bounds( int &X, int &Y, int &W, int &H, int R, int C=0 )
    {
        return false;
    };

    Flv_ShowScrollbar has_scrollbar(void)	//	Get/set scrollbar visibility
    {
        return vhas_scrollbars;
    }
    Flv_ShowScrollbar has_scrollbar( Flv_ShowScrollbar v );

    bool move_row(int amount);	//	Change row # by amount

    int row(void)	//	Get/set current row
    {
        return vrow;
    };
    int row(int n);

    bool row_resizable( int r );	//	Get/Set row locked status
    bool row_resizable( bool n, int r );

    int row_offset(void)	//	Get/Set current row offset
    {
        return vrow_offset;
    }
    int row_offset( int n );

    int rows(void)	//	Get/Set total # of rows
    {
        return vrows;
    };
    int rows(int n);

    int rows_per_page(void)	//	Get/set # of rows / page
    {
        return vrows_per_page;
    }
    int rows_per_page( int n );	//	Use 0 to allow calculating

    bool row_selected(int n);	//	Is row selected?

    int row_width(void)	//	Get/set total row width
    {
        return vrow_width;
    };
    int row_width( int n );

    int scrollbar_width(void)	//	Get/set scrollbar thickness
    {
        return vscrollbar_width;
    }
    int scrollbar_width(int n);

    bool select_locked(void)	//	Allow selecting locked rows/cols?
    {
        return vselect_locked;
    }
    bool select_locked(bool n)	//	Set whether allowing selection of
    {
        return (vselect_locked=n);	   //		locked rows/cols
    }

    int select_start_row(void)	//	Get first selected row
    {
        return vselect_row;
    }
    int select_start_row(int n);	//	Set first selected row

    int top_row(void)	//	Get the current top row
    {
        return vtop_row;
    }
    int top_row(int v)
    {
        return (vtop_row=v);
    };	//	Set the top row (Hint only)

    int why_event()	//	Why was the event called?
    {
        return vwhy_event;
    }
    int why_event( int n )	//	Set why the event was called
    {
        return (vwhy_event=n);
    }

    //	Style routines
    Flv_Style global_style;	//	Global style
    Flv_Style_List row_style;	//	Row styles

    int handle(int event);
	
    DECLARE_CLASS_CHEAP_RTTI_2(Flv_List, Fl_Group)
	
protected:
    int vedit_when;	//	When does editing start
    int edit_row;
    void switch_editor( int nr );
    Fl_Widget *veditor;	//	Current editor
    int vwhy_event;	//	Why was event called
    int vlast_row;	//	Last row highlighted
    void update_top_row(int H);
    void start_draw(int &X, int &Y, int &W, int &H, int &rw);
    virtual void draw_row( int Offset, int &X, int &Y, int &W, int &H, int R );
    void draw_border(Flv_Style &s, int &X, int &Y, int &W, int &H );
    void client_area( int &X, int &Y, int &W, int &H );
    void draw_scrollbars( int &X, int &Y, int &W, int &H );
    void draw();
    int page_size(void);	//	Calculate useable page size

    int vrow;	//	Current selected row
	
	int last_click_timestamp;
	
    unsigned char vmax_clicks;	//	Max clicks allowed
    unsigned char vclicks;
    bool vediting;	//	Are we editing now?
	bool is_dragging;

private:
#ifdef FLTK_2
    static Fl_Style* default_style;
#endif
    void check_cursor(void);	//	Check if resizing allowed here
    bool check_resize(void);	//	true if resizing
    int vcallback_when;	//	When to call back
    Fl_Color vdead_space_color;	//	Dead space color
    Flv_ShowScrollbar vhas_scrollbars;	//	determine scroll bar visibility
    Flv_Feature vfeature;	//	Features (Headers, footers, dividers)
    int vrow_offset;	//	Current left offset for display
    int vrow_width;	//	Total pixel width
    int vrows;	//	Total # of rows to display
    int vrows_per_page;	//	# of rows to advance/page
    int vselect_row;	//	First selected row
    int vscrollbar_width;	//	"thickness" of scrollbar
    int vtop_row;	//	Current top row
    bool vselect_locked;	//	Selected locked entries or skip?
};

#endif
